# -*- encoding: utf-8 -*-
##############################################################################
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as published
#    by the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see http://www.gnu.org/licenses/.
#
##############################################################################

from datetime import datetime
from odoo.exceptions import ValidationError
from odoo.tools import float_compare
from odoo.exceptions import except_orm, Warning, RedirectWarning
import odoo.addons.decimal_precision as dp
from odoo.tools import DEFAULT_SERVER_DATETIME_FORMAT
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from odoo.tools.float_utils import float_round, float_compare


class mrp_bom(models.Model):
    _inherit = 'mrp.bom'

    # product_available = fields.Float(related='product_id.qty_available', string=u"在手")

    # depends_stock_avalible = fields.Boolean(stirng=u'替代，不足使用库存', default=False,
    #                                         help=u"替代使用规则："
    #                                              u"在bom展开时，首先通过编号计算替代组，相互替代料，或者相互替代方案，将会编入一个替代组。"
    #                                              u"在一个替代组中，根据绑定关系来进行区分并优先级排序。优先级高者正常展开，低者展开数量为0.如果优先级相同，则结果按照分配比例调整。"
    #                                              u"如果勾选了使用库存，展开数量将会按照优先级调整，优先级高，使用库存，库存不足，将剩余数量分配给优先级低的物料。")

    @api.multi
    def compute_replace_team(self):
        for bom in self:
            # 首先主要信息来源是编号，所以清除替代组信息，
            for line in bom.bom_line_ids:
                line.replace_team = "0"
            i = 1
            for line in bom.bom_line_ids:
                sequence_code = line.sequence_code
                binding_code = line.binding_code
                # 通过替代关系，首先找有替代组的，直接赋值就好
                if line.replace_team == '0':
                    search_sequence_code = self.env['mrp.bom.line'].search(
                        [('bom_id', '=', bom.id), ('sequence_code', '=', sequence_code), ('sequence_code', '!=', "0"),
                         ('replace_team', '!=', "0")],
                        limit=1)
                    search_binding_code = self.env['mrp.bom.line'].search(
                        [('bom_id', '=', bom.id), ('binding_code', '=', binding_code), ('binding_code', '!=', "0"),
                         ('replace_team', '!=', "0")],
                        limit=1)
                    if search_sequence_code:
                        line.replace_team = search_sequence_code.replace_team
                    # 如果没有替代组，又通过替代关系找不到，那就通过邦定关系找
                    elif search_binding_code:
                        line.replace_team = search_binding_code.replace_team
                    else:
                        line.replace_team = i
                        i += 1

    def explode(self, product, quantity, picking_type=False):
        # self.compute_replace_team()
        boms_done, lines_done = super(mrp_bom, self).explode(product, quantity, picking_type)
        # 对展开的明细进行处理。
        # 1，忽略替代组里面只有一个的，也就是没有替代物料的明细
        # 2,然后以替代组为处理单位，进行计算
        # 2.1，首先看优先级，如果优先级相同，就根据分配比例进行分配。如果有先后优先级，那就直接改数量，优先级高的不变，优先级低的直接调为0

        # 首先进行替代组分组，然后具体操作每个替代组里面的内容
        replace_team_dir = {}
        res_bom_line_qty = {}
        for bom_line in lines_done:
            if not replace_team_dir.get(bom_line[0].replace_team):
                replace_team_dir[bom_line[0].replace_team] = [bom_line[0]]
            else:
                replace_team_dir.get(bom_line[0].replace_team).append(bom_line[0])
        # [替代组---bom行]
        for replace_team_key in replace_team_dir:
            # 只有一个替代组的，就是没有替代料，就不用管
            if len(replace_team_dir[replace_team_key]) <= 1:
                continue
            else:
                # 然后在替代组中进行绑定组分组,分组后，提出优先级，根据优先级来确定调整的比例
                # [邦定组---bom行]
                binding_code_idr = {}
                for team_bom_line in replace_team_dir[replace_team_key]:
                    if not binding_code_idr.get(team_bom_line.binding_code):
                        binding_code_idr[team_bom_line.binding_code] = [team_bom_line]
                    else:
                        binding_code_idr.get(team_bom_line.binding_code).append(team_bom_line)
                # [邦定组--优先级]
                res_priority = {}
                for binding_code_key in binding_code_idr:
                    for binding_bom_line in binding_code_idr[binding_code_key]:
                        res_priority[binding_code_key] = binding_bom_line.replace_priority
                        break
                # 将【绑定组--优先级】根据优先级排序
                res_priority_order = sorted(res_priority.items(), key=lambda d: d[1])
                # [邦定组--调整比例]
                res_ratio = {}
                # 取得最高优先级的值
                min_priority_value = res_priority_order[0][1]
                # 如果最高优先级只有一个，那个其他邦定组的调整比例为0
                i = 0
                for res_priority_key_value in res_priority_order:
                    # 如果当前组的优先级不等于最高优先级，那肯定是要调为0.如果相同优先级且都是最小，先记下来
                    res_priority_key = res_priority_key_value[0]
                    res_priority_value = res_priority_key_value[1]
                    if res_priority_value != min_priority_value:
                        res_ratio[res_priority_key] = 0
                    else:
                        i += 1
                # 如果是多个邦定组，优先级相同，那就按照分配比例来；如果只有一个邦定组，那就调整比例为1
                for res_priority_key_value in res_priority_order:
                    res_priority_key = res_priority_key_value[0]
                    res_priority_value = res_priority_key_value[1]
                    if res_priority_value == min_priority_value:
                        if i > 1:
                            res_ratio[res_priority_key] = binding_code_idr[res_priority_key][0].distribution_ratio
                        else:
                            res_ratio[res_priority_key] = 1
                            break
                # 获得最终的结果：
                # [bom_line_id---更改比例]
                if res_ratio:
                    # [邦定组---更改比例]
                    for res_key in res_ratio:
                        for res_bom_line in binding_code_idr[res_key]:
                            res_bom_line_qty[res_bom_line] = res_ratio[res_key]
        for bom_line_key in res_bom_line_qty:
            for line_done in lines_done:
                if line_done[0] == bom_line_key:
                    line_done[1]['qty'] = line_done[1]['qty'] * res_bom_line_qty[bom_line_key]
                    line_done[1]['original_qty'] = line_done[1]['original_qty'] * res_bom_line_qty[bom_line_key]
                    # 数量调整组
                    # set_bom_line = bom_line
                    # set_bom_line_qty = 1
                    # for compare_bom_line in len(dir[key]):
                    #     if compare_bom_line == set_bom_line:
                    #         continue
                    #     if compare_bom_line.binding_code == set_bom_line.set_bom_line:
                    #         set_bom_line_qty

        return boms_done, lines_done


class mrp_bom_line(models.Model):
    _inherit = ['mrp.bom.line']

    replace_ids = fields.One2many('mrp.product.replace', 'mrp_bom_line_id', u'替代料')

    replace_products = fields.Many2many('mrp.product.replace', string=u'替代料', compute="_get_replace_product")

    sequence_code = fields.Char(u'编号', default="0")
    binding_code = fields.Char(u'邦定', default="0")
    replace_team = fields.Char(u'替代组', default="0")
    replace_priority = fields.Integer(u'优先级', default=3)
    distribution_ratio = fields.Float(u'分配比例', default=1.0)

    @api.one
    @api.depends('replace_ids')
    def _get_replace_product(self):
        self.replace_products = self.replace_ids

    @api.multi
    def action_choose_replace_products(self):
        view = self.env['ir.model.data'].xmlid_to_res_id('mrp_product_replace.view_choose_product_form')
        choose_obj = self.env['choose.product']
        wiz_id = self.env['choose.product'].create({'bom_line_id': self.ids[0]})
        return {
            'name': _('choose.product'),
            'type': 'ir.actions.act_window',
            'view_type': 'form',
            'view_mode': 'form',
            'res_model': 'choose.product',
            'views': [(view, 'form')],
            'view_id': view,
            'target': 'new',
            'res_id': wiz_id.id,
        }
        return {'type': 'ir.actions.act_window_close'}
